/*
* Copyright 2010 Pavel Kozhin 
*
* Licensed under the Apache License, Version 2.0 (the "License"); 
* you may not use this file except in compliance with the License. 
* You may obtain a copy of the License at 
* 
* http://www.apache.org/licenses/LICENSE-2.0
* 
* Unless required by applicable law or agreed to in writing, software 
* distributed  under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
* See the License for the specific language governing permissions and 
* limitations under the License.
*
* Author: Pavel Kozhin.
*/

package org.bookmarksframework.util
{
	import flash.events.Event;
	
	import mx.binding.utils.ChangeWatcher;
	
	public class PropertyBinder
	{
		protected var propName:String;
		
		protected var source:Object = null;
		
		protected var watcher:ChangeWatcher = null;
		
		protected var watchHandler:Function = null;
		
		protected var isFirstBindingIgnored:Boolean = false;
		
		public function PropertyBinder(source:Object, propertyName:String, handler:Function)
		{
			this.source = source;
			propName = propertyName;
			watchHandler = handler;
		}
		
		public function bind(commitOnly:Boolean = true):void
		{
			unbind();
			
			if (ChangeWatcher.canWatch(source, propName, commitOnly))
			{
				watcher = ChangeWatcher.watch(source, propName, changeWatcherHandler, commitOnly);
				_oldValue = value;
				changeWatcherHandler();
			}
		}
		
		public function unbind():void
		{
			if (watcher)
				watcher.unwatch();
		}
		
		protected var _oldValue:*;
		
		public function get oldValue():*
		{
			return _oldValue;
		}
		
		protected var _newValue:*;
		
		public function get newValue():*
		{
			return _newValue;
		}
		
		public function get value():*
		{
			return watcher ? watcher.getValue() : null;
		}
		
		public function set value(value:*):void
		{
			if (_newValue !== value)
			{
				_oldValue = this.value;
				source[propName] = value;
			}
		}
		
		private var _ignoreFirstBinding:Boolean;
		
		public function get ignoreFirstBinding():Boolean
		{
			return _ignoreFirstBinding;
		}
		
		public function set ignoreFirstBinding(value:Boolean):void
		{
			_ignoreFirstBinding = value;
		}
		
		protected function changeWatcherHandler(event:Event = null):void
		{
			var value:* = value;
			
			if (_newValue !== value)
			{
				_oldValue = _newValue;
				_newValue = value;
				
				if (ignoreFirstBinding && !isFirstBindingIgnored)
				{
					isFirstBindingIgnored = true;
					return;
				}
				
				watchHandler(_oldValue, _newValue);
			}
		}
	}
}